/**
 * @file database_config.cpp
 * @brief 数据库配置应用层实现
 * @author liyingcheng <1871304538@qq.com>
 * @date 2025-10-13
 *
 * 职责说明：
 * - config模块负责：配置文件加载、JSON解析、环境变量读取
 * - database_config模块负责：从config获取配置、应用到连接池、验证
 *
 * 设计原则：
 * 1. 单一职责：只负责配置的应用和验证
 * 2. 依赖倒置：依赖config模块，不自己实现加载
 * 3. 环境变量覆盖：支持运行时环境变量覆盖配置文件
 */

#include "database/database_config.h"
#include "LoggerManager.h"
#include <sstream>
#include <cstdlib>

namespace cpp_backend
{
    namespace database
    {

        using namespace logger;

        // ============================================
        // DatabaseConfig 实现
        // ============================================

        DatabaseConfig &DatabaseConfig::Instance()
        {
            static DatabaseConfig instance;
            return instance;
        }

        bool DatabaseConfig::ApplyConfig(const config::Config &global_config)
        {
            try
            {
                LOG_INFO << "Applying database config from global config";

                // 从config模块获取配置
                mysql_config_ = global_config.GetMySQLConfig();
                redis_config_ = global_config.GetRedisConfig();

                // 应用环境变量覆盖（可选，环境变量最高优先级）
                ApplyEnvironmentOverrides();

                // 验证配置
                if (!ValidateConfig())
                {
                    LOG_ERROR << "Database configuration validation failed";
                    return false;
                }

                LOG_INFO << "Database config applied successfully";
                LOG_INFO << "  MySQL: " << mysql_config_.host << ":" << mysql_config_.port
                         << "/" << mysql_config_.database;
                LOG_INFO << "  Redis: " << redis_config_.host << ":" << redis_config_.port
                         << "/" << redis_config_.db_index;

                return true;
            }
            catch (const std::exception &e)
            {
                LOG_ERROR << "Failed to apply database config: " << e.what();
                return false;
            }
        }

        bool DatabaseConfig::ApplyEnvironmentOverrides()
        {
            try
            {
                LOG_DEBUG << "Checking environment variable overrides";

                // MySQL环境变量覆盖
                if (const char *env_host = std::getenv("DB_HOST"))
                {
                    mysql_config_.host = env_host;
                    LOG_INFO << "MySQL host overridden by env: " << mysql_config_.host;
                }

                if (const char *env_port = std::getenv("DB_PORT"))
                {
                    mysql_config_.port = std::atoi(env_port);
                    LOG_INFO << "MySQL port overridden by env: " << mysql_config_.port;
                }

                if (const char *env_db = std::getenv("DB_NAME"))
                {
                    mysql_config_.database = env_db;
                    LOG_INFO << "MySQL database overridden by env: " << mysql_config_.database;
                }

                if (const char *env_user = std::getenv("DB_USER"))
                {
                    mysql_config_.username = env_user;
                    LOG_INFO << "MySQL username overridden by env: " << mysql_config_.username;
                }

                if (const char *env_pass = std::getenv("DB_PASSWORD"))
                {
                    mysql_config_.password = env_pass;
                    LOG_INFO << "MySQL password overridden by env: ******";
                }

                if (const char *env_pool = std::getenv("DB_POOL_SIZE"))
                {
                    mysql_config_.pool_size = std::atoi(env_pool);
                    LOG_INFO << "MySQL pool_size overridden by env: " << mysql_config_.pool_size;
                }

                // Redis环境变量覆盖
                if (const char *env_redis_host = std::getenv("REDIS_HOST"))
                {
                    redis_config_.host = env_redis_host;
                    LOG_INFO << "Redis host overridden by env: " << redis_config_.host;
                }

                if (const char *env_redis_port = std::getenv("REDIS_PORT"))
                {
                    redis_config_.port = std::atoi(env_redis_port);
                    LOG_INFO << "Redis port overridden by env: " << redis_config_.port;
                }

                if (const char *env_redis_pass = std::getenv("REDIS_PASSWORD"))
                {
                    redis_config_.password = env_redis_pass;
                    LOG_INFO << "Redis password overridden by env: ******";
                }

                if (const char *env_redis_db = std::getenv("REDIS_DB"))
                {
                    redis_config_.db_index = std::atoi(env_redis_db);
                    LOG_INFO << "Redis db_index overridden by env: " << redis_config_.db_index;
                }

                return true;
            }
            catch (const std::exception &e)
            {
                LOG_ERROR << "Failed to apply environment overrides: " << e.what();
                return false;
            }
        }

        bool DatabaseConfig::ValidateConfig() const
        {
            // 验证MySQL配置
            if (mysql_config_.host.empty())
            {
                LOG_ERROR << "MySQL host is empty";
                return false;
            }

            if (mysql_config_.port <= 0 || mysql_config_.port > 65535)
            {
                LOG_ERROR << "MySQL port is invalid: " << mysql_config_.port;
                return false;
            }

            if (mysql_config_.database.empty())
            {
                LOG_ERROR << "MySQL database name is empty";
                return false;
            }

            if (mysql_config_.username.empty())
            {
                LOG_ERROR << "MySQL username is empty";
                return false;
            }

            if (mysql_config_.pool_size <= 0 || mysql_config_.pool_size > 200)
            {
                LOG_ERROR << "MySQL pool_size is invalid: " << mysql_config_.pool_size;
                return false;
            }

            // 验证Redis配置
            if (redis_config_.host.empty())
            {
                LOG_ERROR << "Redis host is empty";
                return false;
            }

            if (redis_config_.port <= 0 || redis_config_.port > 65535)
            {
                LOG_ERROR << "Redis port is invalid: " << redis_config_.port;
                return false;
            }

            if (redis_config_.db_index < 0 || redis_config_.db_index > 15)
            {
                LOG_ERROR << "Redis db_index is invalid: " << redis_config_.db_index;
                return false;
            }

            if (redis_config_.pool_size <= 0 || redis_config_.pool_size > 200)
            {
                LOG_ERROR << "Redis pool_size is invalid: " << redis_config_.pool_size;
                return false;
            }

            return true;
        }

        std::string DatabaseConfig::ToString() const
        {
            std::ostringstream oss;
            oss << "Database Configuration:\n";
            oss << "  MySQL:\n";
            oss << "    Host: " << mysql_config_.host << ":" << mysql_config_.port << "\n";
            oss << "    Database: " << mysql_config_.database << "\n";
            oss << "    Username: " << mysql_config_.username << "\n";
            oss << "    Password: ******\n";
            oss << "    Pool Size: " << mysql_config_.pool_size << "\n";
            oss << "    Connect Timeout: " << mysql_config_.connect_timeout << "s\n";
            oss << "  Redis:\n";
            oss << "    Host: " << redis_config_.host << ":" << redis_config_.port << "\n";
            oss << "    DB Index: " << redis_config_.db_index << "\n";
            oss << "    Pool Size: " << redis_config_.pool_size << "\n";
            oss << "    Connect Timeout: " << redis_config_.connect_timeout << "s\n";
            return oss.str();
        }

    } // namespace database
} // namespace file_server
